﻿using Infrastructure.Utils.Helpers;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace  Extended.WPF.Core
{
    [TypeConverter(typeof(ThemeTypeConverter))]
    public class Theme
    {
        #region Members
        private string name;
        private string fullName;
        static readonly Dictionary<string, Theme> ThemeNameHash = new Dictionary<string, Theme>();
        internal static List<Theme> ThemesInternal = new List<Theme>();
        public bool ShowInThemeSelector = true;
        public const string StandardCategory = "Standard Themes";
        public const string DevExpressCategory = "DevExpress Themes";
        public const string DeepBlueName = "DeepBlue";
        public const string DeepBlueFullName = "Deep Blue";
        public static Theme DeepBlue = new Theme(DeepBlueName) { IsStandard = true, FullName = DeepBlueFullName, Category = DevExpressCategory, SmallGlyph = GetThemeGlyphUri(DeepBlueName, false), LargeGlyph = GetThemeGlyphUri(DeepBlueName, true) };
        public const string NoneName = "None";
        public static Theme Default = DeepBlue;
        Assembly assembly = null;
        string publicKeyToken;
        string version;
        string assemblyName;
        #endregion

        #region Construction
        static Theme() {
			RegisterTheme(DeepBlue);

		}
        public Theme(string name) : this(name, name) { }
		public Theme(string name, string fullName, string category = StandardCategory, Uri smallGlyphUri = null, Uri largeGlyphUri = null) {
			Initialize(name, fullName, category, smallGlyphUri, largeGlyphUri);
		}
        #endregion

        #region Properties
        /// <summary>
        /// 默认样式名称
        /// </summary>
        public static string DefaultThemeName { get { return Default.Name; } }
        /// <summary>
        /// 默认样式全称
        /// </summary>
        public static string DefaultThemeFullName { get { return Default.FullName; } }
        /// <summary>
        /// 样式GUID集
        /// </summary>
        protected static Tuple<string, string>[] themeGuids = {
															new Tuple<string, string>(DeepBlueName,		 "D247B88A-7194-4A9E-8838-7A36C55A5F26"),
															};
        public static ReadOnlyCollection<Theme> Themes { get { return ThemesInternal.AsReadOnly(); } }

        public Uri SmallGlyph { get; private set; }
        public Uri LargeGlyph { get; private set; }
        public string Category { get; private set; }
        public string AssemblyName
        {
            get
            {
                if (assemblyName == null)
                {
                    assemblyName = GetAssemblyName();
                }
                return assemblyName;
            }
            set
            {
                if (assemblyName == value)
                    return;
                assemblyName = value;
                ResetAssembly();
            }
        }
        public Assembly Assembly
        {
            get
            {
                if (assembly == null)
                {
                    assembly = GetAssembly();
                }
                return assembly;
            }
        }
        public bool GlobalAssemblyCache
        {
            get
            {
                return !(string.IsNullOrEmpty(Name) || string.IsNullOrEmpty(Version) || string.IsNullOrEmpty(PublicKeyToken));
            }
        }
        public string PublicKeyToken
        {
            get { return publicKeyToken; }
            set
            {
                if (publicKeyToken == value)
                    return;
                publicKeyToken = value;
                ResetAssembly();
            }
        }
        public string Version
        {
            get { return version; }
            set
            {
                if (version == value)
                    return;
                version = value;
                ResetAssembly();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public bool IsStandard { get; set; }

        /// <summary>
        /// 全称
        /// </summary>
        public string FullName
        {
            get
            {
                if (fullName == null)
                    return Name;
                return fullName;
            }
            set
            {
                if (fullName == value)
                    return;
                fullName = value;
            }
        }

        /// <summary>
        /// 名称 
        /// </summary>
        public string Name
        {
            get { return name; }
            private set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException("The Name property can not be empty");
                name = value;
            }
        }
        internal string AssemblyPartialName
        {
            get
            {
                return AssemblyHelper.GetPartialName(Assembly);
            }
        }
        #endregion

        #region Methods

        /// <summary>
        /// 获取程序集的GUID
        /// </summary>
        /// <param name="asm"></param>
        /// <returns></returns>
        protected static string GetAssemblyGUID(System.Reflection.Assembly asm)
        {
            if (asm == null) return null;
            object[] attrs = asm.GetCustomAttributes(typeof(GuidAttribute), false);
            if (attrs.Length > 0)
            {
                GuidAttribute ga = attrs[0] as GuidAttribute;
                return ga != null ? ga.Value : null;
            }
            return null;
        }

        /// <summary>
        /// 获取基础样式的名称
        /// </summary>
        /// <param name="themeName"></param>
        /// <returns></returns>
        public static string GetBaseThemeName(string themeName)
        {
            Theme theme = FindTheme(themeName);
            if (theme != null)
            {
                string cGuid = GetAssemblyGUID(theme.Assembly);
                if (cGuid != null)
                {
                    foreach (Tuple<string, string> tTheme in themeGuids)
                    {
                        if (cGuid == tTheme.Item2) return tTheme.Item1;
                    }
                }
            }
            return null;
        }
        
        /// <summary>
        /// 获取图片路径
        /// </summary>
        /// <param name="themeName"></param>
        /// <param name="isLarge"></param>
        /// <returns></returns>
        static Uri GetThemeGlyphUri(string themeName, bool isLarge) {
			string smallGlyphSuffix = "_16x16.png";
			string largeGlyphSuffix = "_48x48.png";
			string glyphPrefix = string.Format(@"/{0};component/Themes/Images/", AssemblyInfo.SRAssemblyXpfCore);
			string suffix = isLarge ? largeGlyphSuffix : smallGlyphSuffix;
			return new Uri(glyphPrefix + themeName + suffix, UriKind.Relative);
		}

        public static Theme FindTheme(string name) {
			if (name == null)
				name = "";
			Theme theme;
			if (!ThemeNameHash.TryGetValue(name, out theme)) {
				ThemeNameHash.Add(name, FindThemeCore(name));
			}
			return ThemeNameHash[name];
		}

        /// <summary>
        /// 根据名称获取样式对象
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        static Theme FindThemeCore(string name) {
			if (name == "Default")
				return Theme.Default;
			foreach (Theme theme in ThemesInternal)
				if (theme.Name == name)
					return theme;
			return null;
		}

        /// <summary>
        /// 注册样式
        /// </summary>
        /// <param name="theme"></param>
        public static void RegisterTheme(Theme theme) {
			if (FindTheme(theme.name) != null)
				throw new ArgumentException("A theme with the same name already exists");
			ThemeNameHash.Clear();
			ThemesInternal.Add(theme);
		}

        /// <summary>
        /// 获取Assmebly对象
        /// </summary>
        /// <returns></returns>
        protected virtual Assembly GetAssembly()
        {
            if (string.IsNullOrEmpty(Name))
                return null;
            return AssemblyHelper.GetAssembly(AssemblyName);
        }

        /// <summary>
        /// 重置样式
        /// </summary>
        protected void ResetAssembly()
        {
            this.assembly = null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected virtual string GetAssemblyName()
        {
            if (Name == DeepBlue.Name)
            {
                return typeof(Theme).Assembly.FullName;
            }
            if (IsStandard)
            {
                return AssemblyHelper.GetThemeAssemblyFullName(Name);
            }
            if (GlobalAssemblyCache)
            {
                return AssemblyHelper.GetAssemblyFullName(Name, Version, CultureInfo.InvariantCulture, PublicKeyToken);
            }
            return Name;
        }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public static void RemoveAllCustomThemes()
        {
            ThemeNameHash.Clear();
            for (int i = ThemesInternal.Count - 1; i >= 0; i--)
            {
                if (!ThemesInternal[i].IsStandard)
                {
                    ThemesInternal.RemoveAt(i);
                }
            }
        }
        public static bool IsDefaultTheme(string themeName)
        {
            return string.IsNullOrEmpty(themeName) || themeName == DefaultThemeName;
        }
        public override string ToString()
        {
            return FullName;
        }
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public static void RemoveTheme(string name)
        {
            Theme theme = FindTheme(name);
            if (theme == null)
                return;
            ThemeNameHash.Clear();
            ThemesInternal.Remove(theme);
        }
        protected void Initialize(string name, string fullName, string category, Uri smallGlyphUri, Uri largeGlyphUri)
        {
            Name = name;
            FullName = fullName;
            Category = category;
            SmallGlyph = smallGlyphUri;
            LargeGlyph = largeGlyphUri;
        }
        #endregion
    }
}
